#include "../SRC/DF_Common/basis_state.h"
#include "../SRC/DF_Common/com_sparse_row.h"
#include "../SRC/DF_Common/const_nucl.h"
#include "../SRC/DF_Common/coupling_coeff.h"
#include "../SRC/DF_Common/time_count.h"
#include "../SRC/DF_MB/mbpt.h"
#include "../SRC/DF_MB/multi_pack.h"
#include "../SRC/DF_MB/normal_order.h"
#include "../SRC/DF_MB/read_data.h"
#include "../SRC/DF_MB/serial_multi_control.h"
#include <boost/filesystem.hpp>
#include <cmath>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

// using std::cin;
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
namespace bf = boost::filesystem;

// using namespace std;

int main() {

  Time_Count TC_main;
  TC_main.start();
  LEC_CONST LECs;
  const std::string path_out = "serial_dat/Output";
  // bf::path path(path_s);
  if (!bf::exists(path_out)) {
    bf::create_directory(path_out);
  }
  //~~~~~~~~~~~~~~~~ basis ~~~~~~~~~~~~~~~~~~~//
  // Serial_SL ser_t;
  Serial_Multi_SL ser_mul_t;
  SMatrix_Ch mat_s_ch;
  Multi_Pack mulpack;

  std::string path_MP = "../DF_Local/serial_dat/Output_MP/mulpack_serial.dat";
  // std::string path_MP = "serial_dat/mulpack_serial.dat";
  cout << " path_MP : " << path_MP << endl;
  ser_mul_t.load(mulpack, path_MP);
  cout << " ### mulpack.Emax = " << mulpack.E_max << endl;

  mulpack.SP.print("serial_dat/Output/Muli_SP.dat");
  mulpack.SP.print("Output/Muli_SP.dat");

  mulpack.SP.print_Tz("serial_dat/Output/Muli_SP_Tz.dat");
  mulpack.SP.print_Tz("Output/Muli_SP_Tz.dat");

  mulpack.TP.print_Tz("serial_dat/Output/Muli_TP_Tz.dat");
  mulpack.TP.print_Tz("Output/Muli_TP_Tz.dat");

  mulpack.TP.print_channel_Tz("serial_dat/Output/Muli_TP_channel_Tz.dat");
  mulpack.TP.print_channel_Tz("Output/Muli_TP_channel_Tz.dat");

  Norm_Ord_Control norm_ct(mulpack.SP, mulpack.TP, mulpack.vec_Tz_S,
                           mulpack.vec_flag_Tz_S, mulpack.hbar_omega,
                           mulpack.E_max, mulpack.regulator_pow,
                           mulpack.Cut_Lambda);

  string filename_NO = "data/Input/DF.Input";
  norm_ct.get_info(filename_NO);

  //norm_ct.build_First();
  // exit(0);
  norm_ct.build_Second();
  /*
  cout << " --- Start MBPT_SEC --- " << endl;
  MBPT_SEC mb_x(norm_ct.SP, norm_ct.DP, norm_ct);
  mb_x.init();
  // mb_x.print_U("data/mbpt_U.dat");
  cout << "Start print_sec_OB_sep" << endl;
  mb_x.print_sec_OB_sep();
  cout << "Start build_sec_Sm" << endl;
  mb_x.build_sec_Sm();
  mb_x.print_sec_OB_deriva();
  // mb_x.print_sec_OB("data/norm_ord_sec_one_me.res");
  cout << "Start Build TwB_sep" << endl;
  mb_x.build_sec_TwB_sep();
  cout << "Finished Build TwB_sep" << endl;
  mb_x.build_sec_Qm();
  cout << "Finished Build Q" << endl;
  //mb_x.print_sec_TwB();
  //mb_x.print_sec_TwB_deriva();
  // exit(0);

  EFF_KK effkk(mb_x, mb_x.SP, mb_x.DP_Model);
  effkk.init();
  cout << "Start Build KK" << endl;
  //effkk.build_1B();
  effkk.build_2B();
  /*
  cout << "Finished Build KK" << endl;
  effkk.print(); /**/
  // mb_x.print_sec_OB_Luigi("data/norm_ord_sec_one_me_Luigi.res");
  // cout << "Start mulpack.print " << endl;
  // mulpack.print("data/Multi_pack.dat");
  // cout << "Start mulpack.print_Tz " << endl;
  // mulpack.print_Tz("data/Multi_pack_Tz.dat");
  // cout << "Finished Multi Pack " << endl;*/
  cout << " === ALL FINISHED === " << endl;
}
